package cn.edu.sdjzu.knoverse.service.impl;

import cn.edu.sdjzu.knoverse.constant.RedisRankingConstant;
import cn.edu.sdjzu.knoverse.model.vo.ranking.CaseRankingVO;
import cn.edu.sdjzu.knoverse.service.RankingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 排行榜服务实现
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class RankingServiceImpl implements RankingService {

    private final RedisTemplate<String, Object> redisTemplate;

    @Override
    public void incrementCaseClickCount(Long caseId, String caseName, String caseType) {
        try {
            // 使用ZSet存储排行榜数据
            String key = RedisRankingConstant.CASE_RANKING_KEY;
            
            // 构建案例信息，用于存储额外信息
            CaseRankingVO caseInfo = CaseRankingVO.builder()
                    .caseId(caseId.toString())
                    .caseName(caseName)
                    .caseType(caseType)
                    .clickCount(1L) // 默认点击次数，实际使用的是ZSet的score
                    .build();
            
            // 检查元素是否存在
            Double score = redisTemplate.opsForZSet().score(key, caseId.toString());
            
            if (score == null) {
                // 不存在则添加，初始分数为1
                redisTemplate.opsForZSet().add(key, caseId.toString(), 1);
                // 同时在另一个key中存储案例的详细信息
                redisTemplate.opsForHash().put(key + "::info", caseId.toString(), caseInfo);
            } else {
                // 存在则增加分数
                redisTemplate.opsForZSet().incrementScore(key, caseId.toString(), 1);
                
                // 更新案例详细信息中的点击次数
                CaseRankingVO existingInfo = (CaseRankingVO) redisTemplate.opsForHash()
                        .get(key + "::info", caseId.toString());
                if (existingInfo != null) {
                    existingInfo.setClickCount(existingInfo.getClickCount() + 1);
                    redisTemplate.opsForHash().put(key + "::info", caseId.toString(), existingInfo);
                } else {
                    // 如果详细信息不存在，则重新创建
                    caseInfo.setClickCount(score.longValue() + 1);
                    redisTemplate.opsForHash().put(key + "::info", caseId.toString(), caseInfo);
                }
            }
            
            log.info("增加案例[{}]点击量成功", caseId);
        } catch (Exception e) {
            log.error("增加案例点击量失败", e);
        }
    }

    @Override
    public List<CaseRankingVO> getCaseRanking() {
        List<CaseRankingVO> result = new ArrayList<>();
        try {
            String key = RedisRankingConstant.CASE_RANKING_KEY;
            
            // 获取排名前N的案例ID和分数
            Set<ZSetOperations.TypedTuple<Object>> tuples = redisTemplate.opsForZSet().reverseRangeWithScores(
                    key, 0, RedisRankingConstant.CASE_RANKING_SIZE - 1);
            
            if (tuples == null || tuples.isEmpty()) {
                return result;
            }
            
            // 遍历排行榜数据
            for (ZSetOperations.TypedTuple<Object> tuple : tuples) {
                String caseId = Objects.requireNonNull(tuple.getValue()).toString();
                Double score = tuple.getScore();
                
                // 获取案例详细信息
                CaseRankingVO caseInfo = (CaseRankingVO) redisTemplate.opsForHash()
                        .get(key + "::info", caseId);
                
                if (caseInfo != null) {
                    // 确保点击次数与ZSet中的分数一致
                    caseInfo.setClickCount(score.longValue());
                    result.add(caseInfo);
                } else {
                    // 如果没有详细信息，则只添加基本信息
                    CaseRankingVO basicInfo = CaseRankingVO.builder()
                            .caseId(caseId)
                            .clickCount(score.longValue())
                            .caseName("未知案例")
                            .caseType("未知类型")
                            .build();
                    result.add(basicInfo);
                }
            }
            
            log.info("获取案例排行榜成功，共{}条数据", result.size());
        } catch (Exception e) {
            log.error("获取案例排行榜失败", e);
        }
        
        return result;
    }
    
    @Override
    public void removeCaseFromRanking(Long caseId) {
        try {
            String key = RedisRankingConstant.CASE_RANKING_KEY;
            
            // 从排行榜中移除案例
            redisTemplate.opsForZSet().remove(key, caseId.toString());
            
            // 同时删除案例详细信息
            redisTemplate.opsForHash().delete(key + "::info", caseId.toString());
            
            log.info("从排行榜中移除案例[{}]成功", caseId);
        } catch (Exception e) {
            log.error("从排行榜中移除案例失败", e);
        }
    }
} 